package br.ufpb.di.ppgi.util;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import javax.mail.internet.InternetAddress;

import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import org.apache.log4j.Logger;

import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;
import br.ufpb.di.ppgi.apresentacao.SiteConfiguration;
import br.ufpb.di.ppgi.negocio.modelo.contato.IEmail;
import br.ufpb.di.ppgi.negocio.modelo.contato.InternetIdentity;

@Component
@ApplicationScoped
public class Mailer {
	
	private final SiteConfiguration conf;
	
	private static Mailer instance;
	
	public static Mailer getInstance() {
		return instance;
	}
	
	public Mailer(SiteConfiguration conf) {
		this.conf = conf;
		instance = this;
	}

	public void threadedSend(IEmail contato) {
		simpleSend(contato.getDe().getNome(),contato.getDe().getEmail(),contato.getPara().getNome(), contato.getPara().getEmail(), contato.getAssunto(), contato.getMensagemEnviada());
	}

	public void threadedBatchSend(IEmail contato, List<? extends InternetIdentity> cadastrados) {
		batchSend(contato.getDe().getNome(),contato.getDe().getEmail(), cadastrados, contato.getAssunto(), contato.getMensagemEnviada());
	}
	
	private void simpleSend(String nomeFrom,String emailFrom,String nomeTo,String emailTo,String assunto,String conteudo) {
		SimpleEmail simpleEmail;
		
		try {
			simpleEmail = conf.getSimpleEmail();
			simpleEmail.setFrom(emailFrom, nomeFrom, conf.getEmailDefaultCharset());
			simpleEmail.addTo(emailTo,nomeTo, conf.getEmailDefaultCharset());
			simpleEmail.setSubject(assunto);
			simpleEmail.setMsg(conteudo);  

			send(simpleEmail, "Erro ao enviar email para: "+emailTo);
		} catch (EmailException e) {
			Logger.getLogger(Mailer.class).error("Email inválido", e);
			throw new RuntimeException("Erro ao enviar a mensagem",e);
		}
	}
	
	private void batchSend(String nomeFrom,String emailFrom, List<? extends InternetIdentity> cadastrados,String assunto,String conteudo) {
		SimpleEmail simpleEmail;
		
		try {
			List<InternetAddress> destinatarios = new ArrayList<InternetAddress>();
			
			for (InternetIdentity d : cadastrados) {
				if (validateEmail(d))
					destinatarios.add(new InternetAddress(d.getEmail(), d.getNome(), conf.getEmailDefaultCharset())); 
			}
			if (destinatarios.isEmpty())
				throw new IllegalArgumentException("Numeros de distinatários inválidos");
			simpleEmail = conf.getSimpleEmail();
			simpleEmail.setBcc(destinatarios);
			simpleEmail.setSubject(assunto);
			simpleEmail.setMsg(conteudo);
			//simpleEmail.setContent(conteudo, Email.TEXT_HTML); 

			send(simpleEmail, "Erro ao enviar emails em massa.");
		} catch (EmailException e) {
			Logger.getLogger(Mailer.class).error("Email inválido", e);
			throw new RuntimeException("Erro ao enviar a mensagem",e);
		} catch (UnsupportedEncodingException e) {
			Logger.getLogger(Mailer.class).error("Encoding errado", e);
			throw new RuntimeException("Erro ao enviar a mensagem",e);
		}
	}	
	
	
	private class Sender implements Runnable {
		private final SimpleEmail email;
		private final String msgError;

		public Sender(SimpleEmail email, String msgError) {
			this.email = email;
			this.msgError = msgError;
		}

		@Override
		public void run() {
			try {
				email.send();
			} catch(EmailException ex) {
				ex.printStackTrace();
				Logger.getLogger("simtecnologia").error(msgError, ex);
			}
		}
		
	}
	
	private void send(SimpleEmail email, String msgError) {
		new Thread(new Sender(email,msgError)).start();
	}	

	/**
	VALIDADOR DO HIBERNATE
	*/
	/*
	private static String ATOM = "[^\\x00-\\x1F^\\(^\\)^\\<^\\>^\\@^\\,^\\;^\\:^\\\\^\\\"^\\.^\\[^\\]^\\s]";
	private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*";
	private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";
	private static Pattern validEmailPattern = Pattern.compile("^" + ATOM + "+(\\." + ATOM
												+ "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$",
												Pattern.CASE_INSENSITIVE); 
	*/

	// 	VALIDADOR DO JQUERY	
	private static Pattern validEmailPattern = Pattern.compile("^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$");
	
	public boolean validateEmail(InternetIdentity contato) {
		if (contato == null)
			return false;
		if (contato.getEmail().length() == 0)
			return false;

		return validEmailPattern.matcher(contato.getEmail()).matches();
	}
}